#include "RoutingDialog.h"
#include "ui_RoutingDialog.h"

#include <QDebug>

RoutingDialog::RoutingDialog(const CustomerInfo& info,
                             const QList<CustomerPtr>& customerList,
                             DepoPtr depo,
                             QList< QPair<CustomerPtr, RouteType> >& routeList,
                             RouteType& depoRoute,
                             QWidget *parent) :
    QDialog(parent),
    ui(new Ui::RoutingDialog),
    info_(info),
    customerList_(customerList),
    depo_(depo),
    routeList_(routeList),
    depoRoute_(depoRoute),
    isRoutingFailed_(false),
    rowIndex_(0),
    customerIterator_(customerList_.begin())
{
    ui->setupUi(this);
    initCommonUi();

    connect(ui->cancelButton, SIGNAL(clicked()), this, SLOT(breakRouting()));
    connect(ui->okButton, SIGNAL(clicked()), this, SLOT(correctClose()));

    depoRoute_.lineString.reset();
    depoRoute_.weight = 0;

    router_ = new OSRMRouter();
    connect(router_, SIGNAL(routingFinished(int)), this, SLOT(processRoutingResult(int)));

    router_->findRoute(QPointF(depo_->getCoordinate()->longitude(), depo_->getCoordinate()->latitude()),
                       info_.coordinate);
}

RoutingDialog::~RoutingDialog()
{
    delete ui;
    delete router_;
}

void RoutingDialog::initCommonUi()
{
    ui->routeTable->setColumnWidth(ColFrom, 230);
    ui->routeTable->setColumnWidth(ColTo, 230);
    ui->routeTable->setColumnWidth(ColDistance, 120);
    ui->routeTable->setColumnWidth(ColStatus, 120);

    ui->routeTable->setRowCount(customerList_.size() + 1);
    setTableRow("Depo", "Undefined", "Routing...", 0);
    ui->routeTable->item(rowIndex_, ColStatus)->setTextColor(Qt::yellow);

    int index = 1;
    CustomerPtr customer;
    foreach(customer, customerList_)
    {
        setTableRow(customer->getName(), "Undefined", "Undefined", index);
        index++;
    }

    ui->okButton->setEnabled(false);
    ui->progressBar->setMinimum(99);
    ui->progressBar->setMaximum(0);
}

void RoutingDialog::setTableRow(const QString &from, const QString& distance, const QString &status, int index)
{
    ui->routeTable->setItem(index, ColFrom, new QTableWidgetItem(from));
    ui->routeTable->setItem(index, ColTo, new QTableWidgetItem(info_.name));
    ui->routeTable->setItem(index, ColDistance, new QTableWidgetItem(distance));
    ui->routeTable->setItem(index, ColStatus, new QTableWidgetItem(status));
}

void RoutingDialog::processRoutingResult(int error)
{
    QTableWidgetItem* distanceItem = ui->routeTable->item(rowIndex_, ColDistance);
    QTableWidgetItem* statusItem = ui->routeTable->item(rowIndex_, ColStatus);
    if(rowIndex_ == 0) /// Processing depo point
    {
        if(error != OSRMRouter::NO_ERROR)
        {
            distanceItem->setText("Very Big");
            distanceItem->setTextColor(Qt::red);
            statusItem->setText("Failed");
            statusItem->setTextColor(Qt::red);
            isRoutingFailed_ = true;
        }
        else
        {
            depoRoute_.lineString = qPointFListToLineString(router_->currentRouteRef(), "Depo", info_.name);
            depoRoute_.weight = router_->currentRouteWeight();
            distanceItem->setText(QString::number(router_->currentRouteWeight()));
            distanceItem->setTextColor(Qt::green);
            statusItem->setText("Routed");
            statusItem->setTextColor(Qt::green);
        }
        rowIndex_++;
        if(customerIterator_ != customerList_.end())
            startRoutingToCustomer(*customerIterator_);
        else
            finishRouting();
    }
    else
    {
        if(error != OSRMRouter::NO_ERROR)
        {
            distanceItem->setText("Very Big");
            distanceItem->setTextColor(Qt::red);
            statusItem->setText("Failed");
            statusItem->setTextColor(Qt::red);
            isRoutingFailed_ = true;
        }
        else
        {
            distanceItem->setText(QString::number(router_->currentRouteWeight()));
            distanceItem->setTextColor(Qt::green);
            statusItem->setText("Routed");
            statusItem->setTextColor(Qt::green);

            RouteType rt;
            rt.lineString = qPointFListToLineString(router_->currentRouteRef(), (*customerIterator_)->getName(), info_.name);
            rt.weight = router_->currentRouteWeight();
            routeList_.append(QPair<CustomerPtr, RouteType>(*customerIterator_, rt));
        }
        rowIndex_++;
        customerIterator_++;
        if(customerIterator_ != customerList_.end())
            startRoutingToCustomer(*customerIterator_);
        else
            finishRouting();
    }
}

void RoutingDialog::startRoutingToCustomer(CustomerPtr customer)
{
    ui->routeTable->item(rowIndex_, ColStatus)->setTextColor(Qt::yellow);
    ui->routeTable->item(rowIndex_, ColStatus)->setText("Routing...");

    router_->findRoute(QPointF(customer->getCoordinate()->longitude(), customer->getCoordinate()->latitude()),
                       info_.coordinate);
}

void RoutingDialog::finishRouting()
{
    ui->progressBar->setMinimum(0);
    ui->progressBar->setMaximum(100);
    ui->progressBar->setValue(100);

    ui->okButton->setEnabled(true);
}

LineStringPtr RoutingDialog::qPointFListToLineString(const QList<QPointF> &pointsF, QString from, QString to)
{
    if(pointsF.empty())
        return LineStringPtr();

    QList<qmapcontrol::Point*> points;
    QPointF pointF;
    foreach(pointF, pointsF)
        points.append(new qmapcontrol::Point(pointF.x(), pointF.y()));

    QPen* linepen = VRPPixmapsFactory::instance()->routePen();
    QString lineStringName = "From " + from + " to " + to;
    return LineStringPtr(new qmapcontrol::LineString(points, lineStringName, linepen));
}

void RoutingDialog::breakRouting()
{
    this->reject();
}

void RoutingDialog::correctClose()
{
    if(!isRoutingFailed_)
        this->accept();
    else
        this->reject();
}
